﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Modelo;
using PloobsEngine.SceneControl;
using PloobsEngine.Cameras;
using PloobsEngine.Light;

namespace PloobsEngine.Material
{
    public enum ReflectionType
    {
        PerfectMirror, ReflexiveSurface
    }

    public class EMReflective : IShader
    {        
        private Effect _shader;  
        private float specularIntensity = 0f;
        private TextureCube texCube;        
        private String texName = null;
        private ReflectionType rType = ReflectionType.ReflexiveSurface;       
 
        /// <summary>
        /// from 0 to 1 
        /// default 0.5f
        /// 1 = perfect mirror
        /// </summary>
        private float reflectionIndex = 0.5f;

        public float ReflectionIndex
        {
            get { return reflectionIndex; }
            set { reflectionIndex = value; }
        }  
        

        public TextureCube TextureCube
        {
            get { return texCube; }
            set { texCube = value; }
        }
        
        public EMReflective()
        {        
        }

        public EMReflective(String texName , ReflectionType type  )
        {            
            this.rType = type;
            this.texName = texName;
            texCube = EngineStuff.CustomContentManager.GetAsset<TextureCube>(texName);
        }

        public EMReflective(String texName,float reflectionIndex)
        {
            this.reflectionIndex = reflectionIndex;
            this.texName = texName;
         
        }

        public float SpecularIntensity
        {
            get { return specularIntensity; }
            set { specularIntensity = value; }
        }
        private float specularPower = 0f;

        public float SpecularPower
        {
            get { return specularPower; }
            set { specularPower = value; }
        }

        public override void PreUpdate(IObject ent, IList<ILight> lights)
        {
            if (rType == ReflectionType.PerfectMirror)
                this._shader.CurrentTechnique = this._shader.Techniques["PerfectMirror"];
            else if (rType == ReflectionType.ReflexiveSurface)
                this._shader.CurrentTechnique = this._shader.Techniques["ReflexiveSurface"];
            
            this._shader.Parameters["id"].SetValue(shaderId);

            this._shader.Parameters["reflectionIndex"].SetValue(reflectionIndex);
            if (rType == ReflectionType.ReflexiveSurface)
                this._shader.Parameters["Texture"].SetValue(ent.Modelo.getTexture(TextureType.DIFFUSE));

            this._shader.Parameters["specularIntensity"].SetValue(specularIntensity);
            this._shader.Parameters["specularPower"].SetValue(specularPower);

        }
       
        public override void Draw(IModelo modelo, IRenderHelper render, ICamera camera)
        {
            if (obj != null)
            {
                this._shader.Parameters["View"].SetValue(camera.View);
                this._shader.Parameters["Projection"].SetValue(camera.Projection);
                this._shader.Parameters["Cubemap"].SetValue(texCube);

                Matrix[] boneTransforms = modelo.getBonesTransformation();
                Matrix wld = obj.getWorldMatrix();

                for (int i = 0; i < modelo.MeshNumber; i++)
                {
                    BatchInformation[] bi = modelo.GetBatchInformation(i);
                    Matrix w1 = Matrix.Multiply(wld, boneTransforms[modelo.GetParentBoneIndex(i)]);
                    this._shader.Parameters["World"].SetValue(w1);                        
                    for (int j = 0; j < bi.Count(); j++)
                    {

                        this._shader.Begin();
                        EngineStuff.GraphicsDevice.VertexDeclaration = bi[j].VertexDeclaration;
                        EngineStuff.GraphicsDevice.Vertices[0].SetSource(modelo.GetVertexBuffer(i), bi[j].StreamOffset, bi[j].VertexStride);
                        EngineStuff.GraphicsDevice.Indices = modelo.GetIndexBuffer(i);

                        this._shader.CurrentTechnique.Passes[0].Begin();
                        EngineStuff.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, bi[j].BaseVertex, 0, bi[j].NumVertices, bi[j].StartIndex, bi[j].PrimitiveCount);
                        this._shader.CurrentTechnique.Passes[0].End();
                        this._shader.End();
                    }

                }
            }
        }

        public override MaterialType MaterialType
        {
            get { return MaterialType.DEFERRED; }
        }

        public override void Initialize()
        {
            this._shader = EngineStuff.InternalContentManager.GetAsset<Effect>("EMSHADER");            
            texCube = EngineStuff.CustomContentManager.GetAsset<TextureCube>(texName);
            base.Initialize();
        }
      

    }
}
